--
-- Author: dbliu
-- Date: 2014-02-27 15:30:20
--


--=model=========================================================================================================
local EM = import("..EM")
local EMEntityMgr = class("EMEntityMgr", EM)
local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")

-- 定义事件
EMEntityMgr.START_EVENT = "START_EVENT"
EMEntityMgr.KILL_EVENT = "KILL_EVENT"

EMEntityMgr.schema = clone(EM.schema)
EMEntityMgr.schema["nickname"] = {"string"} -- 字符串类型，没有默认值
EMEntityMgr.schema["minDelay"]    = {"number", 0} -- 数值类型，默认值 0
EMEntityMgr.schema["maxDelay"]       = {"number", 0}
EMEntityMgr.schema["minVelocity"]    = {"number", 0} 
EMEntityMgr.schema["maxVelocity"]       = {"number", 0}

function EMEntityMgr:ctor(properties, events, callbacks)

	local defaultEvents = {
		-- 开火
        {name = "fire",   from = "idle",    to = "firing"},
        -- 开火冷却结束
        {name = "fire_finish",  from = "firing",  to = "idle"},
	}

	-- 如果继承类提供了其他事件，则合并
	table.insertTo(defaultEvents, totable(events))

	-- 设计状态机的默认回调
	local defaultCallbacks = {	
		onleavefiring = handler(self, self.onLeaveFiring_),
	}

	-- 如果继承类提供了其他回调，则合并
	table.merge(defaultCallbacks,totable(callbacks))

	EMEntityMgr.super.ctor(self,properties, defaultEvents, defaultCallbacks)

end


function EMEntityMgr:canFire()
    return self:getFSM():canDoEvent("fire")
end

function EMEntityMgr:onLeaveFiring_(event)

	

    local cooldown = tonum(event.args[1])
    if cooldown > 0 then

    	local thz = self 
    	--print(cooldown)

        -- 如果开火后的冷却时间大于 0，则需要等待
        scheduler.performWithDelayGlobal(function()

        	if thz:getFSM():getState()=="dead" then
        		event.cancel()
        	else
        		event.transition()
        	end

        end, cooldown)
        return "async"
    end
end

--=view=========================================================================================================
--不可见


--=controller=========================================================================================================

local Enemy1Controller = import(".ECEnemy1")
local Enemy2Controller = import(".ECEnemy2")
local Enemy3Controller = import(".ECEnemy3")

local PropBombController = import(".ECPropBomb")
local PropBulletController = import(".ECPropBullet")


local ECEntityMgr = class("ECEntityMgr",function ()
	return display.newNode()
end)

function ECEntityMgr:ctor(x,y)

   	local eMTables={}
   	eMTables[1]={id="enemy1_manager",minDelay=0,maxDelay=1,minVelocity=100,maxVelocity=200}
   	eMTables[2]={id="enemy2_manager",minDelay=1,maxDelay=5,minVelocity=90,maxVelocity=180}
   	eMTables[3]={id="enemy3_manager",minDelay=3,maxDelay=10,minVelocity=70,maxVelocity=150}
   	eMTables[4]={id="prop_bullet_manager",minDelay=10,maxDelay=30}
   	eMTables[5]={id="prop_bomb_manager",minDelay=20,maxDelay=60}

    self.fsm_list={}
   	for key=1,5 do
    	self.fsm_list[key] = EMEntityMgr.new(eMTables[key])
		self.fsm_list[key]:getComponent("components.behavior.StateMachine"):exportMethods()
		self.fsm_list[key]:doEvent("start") 
    end

   	self.eClist={}
   	self.eClist[1]=Enemy1Controller
   	self.eClist[2]=Enemy3Controller
   	self.eClist[3]=Enemy2Controller
   	self.eClist[4]=PropBulletController
   	self.eClist[5]=PropBombController

    self.total_game_time=0

    -- 注册帧事件
    self:addScriptEventListener(cc.Event.ENTER_FRAME, handler(self, self.tick))

--[[
     -- 在视图清理后，检查模型上注册的事件，看看是否存在内存泄露
    self:addScriptEventListener(cc.Event.CLEANUP, function()
        self.model_:getComponent("components.behavior.EventProtocol"):dumpAllEventListeners()
    end)
]]
end

function ECEntityMgr:tick( dt )
    for i=1,5 do
    	self:fire(i)
    end

    self:increase_difficulty(dt)

    self:checkLifeCycle()
end


function ECEntityMgr:fire( id )
    local fsm = self.fsm_list[id]
    if fsm:canDoEvent("fire") then
        fsm:doEvent("fire")
        fsm:doEvent("fire_finish", math.random(self.fsm_list[id].minDelay_,self.fsm_list[id].maxDelay_))
        
        if id == 4 or id == 5 then
        	local enemy=self.eClist[id].new(math.random(20,640-20),app.flightDistance+1):addTo(app.maplayer,3)
        else
        	local enemy=self.eClist[id].new(math.random(20,640-20),display.top+app.flightDistance+960):addTo(app.maplayer,3-id)
          enemy.view_.body_:setVelocity(0,-math.random(self.fsm_list[id].minVelocity_,self.fsm_list[id].maxVelocity_))
          --添加到enemy_list,用于范围伤害检测
          app:add_enemy(enemy)
        end
      	
    end
end

function ECEntityMgr:increase_difficulty( dt )

  dt=dt*4  --难度提升系数

  self.total_game_time=dt+self.total_game_time
  self.fsm_list[1].minVelocity_=self.fsm_list[1].minVelocity_+dt
  self.fsm_list[2].minVelocity_=self.fsm_list[2].minVelocity_+dt
  self.fsm_list[3].minVelocity_=self.fsm_list[3].minVelocity_+dt

  self.fsm_list[1].maxVelocity_=self.fsm_list[1].maxVelocity_+dt*0.1
  self.fsm_list[2].maxVelocity_=self.fsm_list[2].maxVelocity_+dt*0.1
  self.fsm_list[3].maxVelocity_=self.fsm_list[3].maxVelocity_+dt*0.1

  self.fsm_list[1].minDelay_=self.fsm_list[1].minDelay_
  self.fsm_list[2].minDelay_=self.fsm_list[2].minDelay_-dt*0.001
  self.fsm_list[3].minDelay_=self.fsm_list[3].minDelay_-dt*0.0005

  self.fsm_list[1].maxDelay_=self.fsm_list[1].maxDelay_-dt*0.0005
  self.fsm_list[2].maxDelay_=self.fsm_list[2].maxDelay_-dt*0.001
  self.fsm_list[3].maxDelay_=self.fsm_list[3].maxDelay_-dt*0.001
end

function ECEntityMgr:kill_all(  )
    for index = #app.enemy_list_in_scene, 1, -1 do
        local tmp_ = app.enemy_list_in_scene[index]
        if tmp_.view_ then
          
            table.remove(app.enemy_list_in_scene, index)

            tmp_.view_.body_:removeSelf(false)
            tmp_.view_.body_=nil

            

            --tmp_:removeSelf(true)
            tmp_:be_kill()
            
            
        end
        
    end
end

function ECEntityMgr:kill_all_delay()
    
end


function ECEntityMgr:checkLifeCycle()

    for index = #app.enemy_list_in_scene, 1, -1 do
        local tmp_ = app.enemy_list_in_scene[index]
        if tmp_.view_ then
            local p = tmp_.view_:getSpritePosition()
            --print(p.y)
            
            if p.y<app.flightDistance then
              
                table.remove(app.enemy_list_in_scene, index)

                tmp_.view_.body_:removeSelf(false)
                tmp_.view_.body_=nil

                

                tmp_:removeSelf(true)

            end
            
        end
        
    end

    
end



return ECEntityMgr
